<?PHP
/*   This is a BSD style permissive license.
*    This module is original work by the author.
*
* Copyright (c) 2007, iNetOffice, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of iNetOffice nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY iNetOffice ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL iNetOffice BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Author: Tom Snyder, iNetOffice, Inc.
*/

/* opensam_validate_adf.php -- fetch, validate, and display an 
 *    Application Description File
 */
 
require_once( "opensam_parse_adf.php" );

$adf_file_in = "";

if( !empty( $_GET['adf_url'] ) ) {
  $adf_file_in = $adf_file = $_GET['adf_url'];
  // validate it....
  
  // Be flexible about what they enter:
  // opensam file:
  if( !ereg( "opensamadf.rdf$", $adf_file ) ) {
    if( !ereg( "/$", $adf_file ) ) $adf_file .= "/";
    $adf_file .= "opensamadf.rdf";
  }
  
  // Double slash:
  if( !ereg( "[^/]*//", $adf_file ) ) $adf_file = "//" . $adf_file;
  if( !ereg( "^https?:", $adf_file ) ) $adf_file = "http:" . $adf_file;
  
  $Msg1 = "Validating $adf_file";
  $ErrMsg   = "";
  $InvalidMsg = "";
  $WarningMsg = "";
  
  do { // not actually a loop, we use do{} just for the handy break functionality.
  
    $adf_string = @file_get_contents( $adf_file );
    if( empty( $adf_string ) ) {
      $ErrMsg = "Could not read Application Description File $adf_file.";
      break;
    }
    $opensam_adf_obj = new OpenSAM_ADF( $adf_string );
    $opensam_adf_values = $opensam_adf_obj->parse_adf_return_simple_array();
	
    if( !is_array( $opensam_adf_values ) ) {
      $ErrMsg = "FAILED parsing $adf_file - $opensam_adf_values";
      break;
    }

    // Diagnostic: 
    //$opensam_adf_obj->dump_this_guy();   
    
    // We've got the details from the ADF. Now build the dump table and validate the
    // values.
    
    $DumpTable = "<table cellpadding=2 cellspacing=0 border=0>";
    dump_check_value( $DumpTable, $InvalidMsg, "Canonical URL", $opensam_adf_values['Description'], true );
    dump_check_value( $DumpTable, $InvalidMsg, "Application Name", $opensam_adf_values['title'] );
    dump_check_value( $DumpTable, $InvalidMsg, "Description", $opensam_adf_values['description'] );
    dump_check_value( $DumpTable, $InvalidMsg, "Owner", $opensam_adf_values['author'] );
    dump_check_value( $DumpTable, $InvalidMsg, "Instance Host", $opensam_adf_values['publisher'] );
    
    // Gather the application types:
    $apptypes = ""; 
    if( is_nested_value( $opensam_adf_values['applicationType'] ) ) {
      $apptypes = implode_values( ", ", $opensam_adf_values['applicationType'] );
    
      if( false === has_nested_value( 'Web20', $opensam_adf_values['applicationType'] ) )
        $WarningMsg .= "WARNING: Web20 not included in applicationType list<br>";
      if(  false === has_nested_value( 'OpenSAM', $opensam_adf_values['applicationType'] ) )
        $WarningMsg .= "WARNING: OpenSAM not included in applicationType list<br>";
    }
    dump_check_value( $DumpTable, $InvalidMsg, "Application Types", $apptypes );
    
    // Gather openSAM Types:
    $opensam_types = "";
    if( is_nested_value( $opensam_adf_values['openSAMType'] ) ) {
      $opensam_types = implode_values( ", ", $opensam_adf_values['openSAMType'] );
    }
    dump_check_value( $DumpTable, $InvalidMsg, "OpenSAM Types", $opensam_types );
    
    if( is_nested_value( $opensam_adf_values['openSAMType'] ) ) {
      // Check for all the URIs associated with the OpenSAM types:
      if( false !== has_nested_value( 'belaunched', $opensam_adf_values['openSAMType'] ) ) {
          dump_check_value( $DumpTable, $InvalidMsg, "Launch URL", $opensam_adf_values['openSAMLaunchURI'] );
      }
      if( false !== has_nested_value( 'storage', $opensam_adf_values['openSAMType'] ) ) {
          dump_check_value( $DumpTable, $InvalidMsg, "WebDAV URL", $opensam_adf_values['openSAMWebDAVURI'] );
      }
      if( false !== has_nested_value( 'launch', $opensam_adf_values['openSAMType'] ) ) {
          dump_check_value( $DumpTable, $InvalidMsg, "Launch Dispatch URL", $opensam_adf_values['openSAMLaunchDispatchURI'], true );
      }
      if( false !== has_nested_value( 'search', $opensam_adf_values['openSAMType'] ) ) {
          dump_check_value( $DumpTable, $InvalidMsg, "Search URL", $opensam_adf_values['openSAMSearchURI'], true );
      }
      if( false !== has_nested_value( 'emailsend', $opensam_adf_values['openSAMType'] ) ) {
          dump_check_value( $DumpTable, $InvalidMsg, "Compose Email URL", $opensam_adf_values['openSAMComposeEmailURI'], true );
      }
      if( false !== has_nested_value( 'addressbook', $opensam_adf_values['openSAMType'] ) ) {
          dump_check_value( $DumpTable, $InvalidMsg, "Address Book URL (LDAP)", $opensam_adf_values['openSAMAddressBookURI'], true );
      }
    }
    
    // Gather File Types:
    $file_types_handled = "";
    if( is_nested_value( $opensam_adf_values['fileTypes'] ) ) {
      $file_types_handled = implode_values( ", ", $opensam_adf_values['fileTypes'] );
    }
    dump_check_value( $DumpTable, $InvalidMsg, "File Types Handled", $file_types_handled );
    
    dump_check_value( $DumpTable, $InvalidMsg, "Home Page", $opensam_adf_values['homePage'], true );
    dump_check_value( $DumpTable, $InvalidMsg, "Help Page", $opensam_adf_values['helpPage'], true );
    dump_check_value( $DumpTable, $InvalidMsg, "Signup Page", $opensam_adf_values['signupPage'], true );
    dump_check_value( $DumpTable, $InvalidMsg, "EULA Page", $opensam_adf_values['eulaPage'], true );
    
    dump_value( $DumpTable, "Free Trial Length, in days", $opensam_adf_values['freeTrialDays'] );
    dump_value( $DumpTable, "Price", $opensam_adf_values['price'] );
    dump_value( $DumpTable, "Hosting Options", $opensam_adf_values['hosting'] );
    
    dump_check_value( $DumpTable, $InvalidMsg, "App Brief Label", $opensam_adf_values['nameLabel'] );
    dump_check_value( $DumpTable, $InvalidMsg, "App Tag-line", $opensam_adf_values['nameTagline'] );
    
    $logo_html = "";
    $logo_dark_html = "<div style=\"background-color:#D0D0D0\">";
    foreach( $opensam_adf_values['logos']['_collection_'] as $alogo ) {
      if( empty( $alogo['width'] ) ) $InvalidMsg .= "A logo element is missing the width: attribute<br>";
      if( empty( $alogo['height'] ) ) $InvalidMsg .= "A logo element is missing the height: attribute<br>";
      $logo_1img = "<img src=\"".$alogo['value']."\" width=".$alogo['width']." height=".$alogo['height']."\"> &nbsp;&nbsp; ";
      $logo_html .= $logo_1img;
      $logo_dark_html .= $logo_1img;
    }
    $pass_in_value = array( 'value' => $logo_html );
    dump_check_value( $DumpTable, $InvalidMsg, "Logos of various sizes", $pass_in_value );
    $pass_in_value = array( 'value' => $logo_dark_html . "</div>" );
    dump_check_value( $DumpTable, $InvalidMsg, "Logos on gray background (use .png for best results)", $pass_in_value );


    // 
    // WRAP UP and combine messages:
    //
    $ErrMsg .= $InvalidMsg . $WarningMsg; 
    
    $DumpTable .= "</table>";
    
    //dump_check_value( $DumpTable, $InvalidMsg, "", $opensam_adf_values[''] );
    if( empty( $InvalidMsg ) ) $Msg1 .= ". . . . . VALID";
    else $Msg1 .= "...INVALID!";
    
    
  } while( false );
}

// Some values we get back in the 'simple' array are have arrays contained in their ['value']
// guy. These are values that correspond to sets of nodes in a <rdf:Bag> or some such.
//  RETURNS: true if this value is one of those nested array values.
function is_nested_value( &$check_this ) {
  return( array_key_exists( '_collection_', $check_this ) );
}

// Does a certain value exist in our nested object?
function has_nested_value( $searchvalue, &$collection ) {
  foreach( $collection['_collection_'] as $oneitem ) {
    if( array_key_exists( 'value', $oneitem ) && $oneitem['value'] == $searchvalue )
      return( true );
  }
  return( false );
}

function implode_values( $sep, &$array_with_values ) {
  if( !is_array( $array_with_values ) || !array_key_exists( '_collection_', $array_with_values ) )
    return( "" );  // safety.
  $ret = "";
  $sep2use = "";
  foreach( $array_with_values['_collection_'] as $oneval ) {
    if( array_key_exists( 'value', $oneval ) ) {
      $ret .= $sep2use . $oneval['value'];
      $sep2use = $sep;
    }
  }
  return( $ret );
}

function dump_value( &$DumpTable, $value_name, $value_value ) {
  // Values can come in as sub elements in an array or come in directly:
  if( is_array( $value_value ) ) $value = $value_value['value'];
  else $value = $value_value;
  
  if( !empty( $value ) ) {
    //if( $fLink ) $value = "<a href=\"$value\">".$value."</a>";
    $DumpTable .= "<tr><td class=l>$value_name:</td><td class=r>$value</td></tr>\n";
  }
}

function dump_check_value( &$DumpTable, &$InvalidMsg, $value_name, $value_value, $fLink = false ) {
  // Values can come in as sub elements in an array or come in directly:
  if( is_array( $value_value ) ) $value = $value_value['value'];
  else $value = $value_value;
  
  if( empty( $value ) ) $InvalidMsg .= "INVALID: $value_name not supplied<br>";
  else {
    if( $fLink ) $value = "<a href=\"$value\">$value</a>";
    $DumpTable .= "<tr><td class=l>$value_name:</td><td class=r>$value</td></tr>\n";
  }
}

?>
<html><head><title>ADF Validator</title>
<STYLE title=inetWord type=text/css>TD.iNetwordTDBrdr {
	BORDER-RIGHT: black 1pt solid; PADDING-RIGHT: 5.5pt; BORDER-TOP: black 1pt solid; PADDING-LEFT: 5.5pt; VERTICAL-ALIGN: top; BORDER-LEFT: black 1pt solid; BORDER-BOTTOM: black 1pt solid; BACKGROUND-COLOR: transparent; netwrd-type: internal
}
TD.iNetwordTD {
	PADDING-RIGHT: 5.5pt; PADDING-LEFT: 5.5pt; VERTICAL-ALIGN: top; BACKGROUND-COLOR: transparent; netwrd-type: internal
}
TABLE.iNetwordTABLE {
	BORDER-COLLAPSE: collapse; netwrd-type: internal
}
H1.MsoNormal {
	FONT-WEIGHT: bold; FONT-SIZE: 16pt; MARGIN: 12pt auto 6pt; FONT-FAMILY: Arial; mso-style-name: "Heading 1"
}
H2.MsoNormal {
	FONT-WEIGHT: bold; FONT-SIZE: 14pt; MARGIN: 12pt auto 3pt; FONT-STYLE: italic; FONT-FAMILY: Arial; mso-style-name: "Heading 2"
}
H3.MsoNormal {
	FONT-WEIGHT: bold; FONT-SIZE: 13pt; MARGIN: 12pt auto 3pt; FONT-FAMILY: Arial; mso-style-name: "Heading 3"
}
.iNetwordPageBreak {
	DISPLAY: block; BACKGROUND-IMAGE: url(/s/i/bg_pagebreak.gif); PAGE-BREAK-BEFORE: always; WIDTH: 100%; HEIGHT: 10px; netwrd-type: internal
}
TD {
	netwrd-type: internal
}
.MsoNormal, .l, .r {
	MARGIN-TOP: 0in; FONT-WEIGHT: 400; FONT-SIZE: 11pt; MARGIN-BOTTOM: 0in; TEXT-INDENT: 0pt; FONT-STYLE: normal; FONT-FAMILY: Tahoma; TEXT-ALIGN: left; mso-style-name: "Normal"
}
.l { PADDING-RIGHT:4px; TEXT-ALIGN:right; background-color: #9ACF19;
}
.modest {
	MARGIN-TOP: 0in; FONT-WEIGHT: 400; FONT-SIZE: 10pt; MARGIN-BOTTOM: 0in; TEXT-INDENT: 0pt; FONT-STYLE: normal; FONT-FAMILY: Tahoma; TEXT-ALIGN: left; mso-style-name: "Normal"
}
.error {
	PADDING: 4px; FONT-SIZE: 11pt; TEXT-INDENT: 0pt; FONT-STYLE: normal; FONT-FAMILY: Tahoma; TEXT-ALIGN: left; background-color:yellow
}
</STYLE>
</head>
<body style="margin:0px; padding:0px">
<DIV style="background-image: url( http://www.opensam.org/pics/opensam%20logos/opensource_tools_bg.png )">
<IMG src="http://www.opensam.org/pics/opensam%20logos/opensource_tools_bg.png"></DIV>
<DIV style="padding:48px 36px 36px 36px">
<DIV class=MsoNormal style="TEXT-ALIGN: left" align=left>
<TABLE class=iNetwordTABLE style="MARGIN-LEFT: 0px; MARGIN-RIGHT: auto; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=iNetwordTD style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; PADDING-TOP: 0px">
<P style="MARGIN-BOTTOM: 0px"><A href="//www.opensam.org"><IMG height=65 src="http://www.opensam.org/pics/opensam%20logos/opensam_button_140x.png" width=140 border=0 x_orig_height="65" x_orig_width="140"></A></P></TD>
<TD class=iNetwordTD style="PADDING-RIGHT: 5.5pt; PADDING-LEFT: 30px; VERTICAL-ALIGN: middle">
<H1 class=MsoNormal style="MARGIN-TOP: 0pt;">Application&nbsp;Description File (ADF)</H1>
<DIV class=MsoNormal style="TEXT-ALIGN: left" align=left>
<TABLE class=iNetwordTABLE style="MARGIN-LEFT: 0px; MARGIN-RIGHT: auto; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=iNetwordTD>
<P class=modest style="TEXT-ALIGN: right" align=right>specification:</P></TD>
<TD class=iNetwordTD>
<P class=modest><A href="http://www.opensam.org/4.0%20Application%20Connections.html">4.0 Application Connections</A></P></TD></TR>
<TR>
<TD class=iNetwordTD>
<P class=modest style="TEXT-ALIGN: right" align=right>downloads:</P></TD>
<TD class=iNetwordTD>
<P class=modest><a href="opensamadf.rdf">Sample ADF file</a>&nbsp;&nbsp;&nbsp;<a href="opensam_parse_adf.php.txt">ADF parsing module</a>
&nbsp;&nbsp;<a href="opensam_validate_adf.php.txt">code for this page</a></P></TD></TR></TBODY></TABLE></DIV>
</TD></TR></TBODY></TABLE></DIV>
<form name=frm action="opensam_validate_adf.php" method=GET>
<p class=MsoNormal>&nbsp;</p>
<h3 class=MsoNormal>Validate and Display ADF</h3>
<p class=MsoNormal>Enter application URL:<br><input type=text size=60 name=adf_url value="<?PHP print $adf_file_in; ?>">
&nbsp;&nbsp;<small><a onclick="document.forms['frm']['adf_url'].value='http://opensam.inetword.com/';return(false)" href="/">try iNetWord</a></small></p><p class=MsoNormal style="padding:6pt"><input type=submit value="Validate"></p>
</form>
<?PHP 
  if( !empty( $Msg1 ) ) { print "<p class=MsoNormal><br>$Msg1</p>\n"; } 
  if( !empty( $ErrMsg ) ) { print "<p class=error>$ErrMsg</p>\n"; } 
  print "<p class=MsoNormal>&nbsp;</p>";
  if( !empty( $DumpTable ) ) {
    print "<div style=\"border: 8px solid #9ACF19\">"; 
    print $DumpTable;
    print "</div>";
  }
?>
</DIV>
</body>
</html>
